package com.liuhao.ssm.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 日期常用工具类
 * Created by liuHao on 2017/5/24.
 */
public class DateUtil {

    /**
     * 获取系统当前时间
     *
     * @return Data
     */
    public static Date getSysDate() {
        Date sysDate = new Date();
        return sysDate;
    }

    /**
     * 获取系统当前时间字符串
     *
     * @param pattern 自定义输出格式（yyyy-MM-dd HH:mm:ss）
     * @return String
     */
    public static String getCurrentDateStr(String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Calendar cal = Calendar.getInstance();
        return dateFormat.format(cal.getTime());
    }

    /**
     * 字符串转日期对象
     *
     * @param dateStr 日期字符串
     * @param pattern 输入日期的格式（yyyy-MM-dd HH:mm:ss）
     * @return Date
     */
    public static Date parseStringToDate(String dateStr, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 日期对象转字符串
     *
     * @param date    日期对象
     * @param pattern 输出字符串的格式（yyyy-MM-dd HH:mm:ss）
     * @return String
     */
    public static String formatDateToString(Date date, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.format(date);
    }

    /**
     * 格式化日期字符串
     *
     * @param dateStr    原日期字符串
     * @param oldPattern 原日期字符串的格式（yyyy-MM-dd HH:mm:ss）
     * @param newPattern 新日期字符串的格式（yyyy-MM-dd HH:mm:ss）
     * @return 新的日期字符串
     */
    public static String reformatDateString(String dateStr, String oldPattern, String newPattern) {
        SimpleDateFormat oldFormat = new SimpleDateFormat(oldPattern);
        SimpleDateFormat newFormat = new SimpleDateFormat(newPattern);
        String reformattedStr = "";
        try {
            reformattedStr = newFormat.format(oldFormat.parse(dateStr));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return reformattedStr;
    }

    /**
     * 获取指定日期+n天的日期
     *
     * @param date 日期
     * @param n    -1表示昨天，+1表示明天，依次类推
     * @return +n天的日期
     */
    public static Date getDateIncreaseDay(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_YEAR, n);
        return cal.getTime();
    }

    /**
     * 获取指定日期+n月的日期
     *
     * @param date 日期
     * @param n    -1表示上个月，+1表示下个月，依次类推
     * @return +n月的日期
     */
    public static Date getDateIncreaseMonth(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, n);
        return cal.getTime();
    }

    /**
     * 获取指定日期+n年的日期
     *
     * @param date 日期
     * @param n    -1表示上一年，+1表示下一年，依次类推
     * @return +n年时的日期
     */
    public static Date getDateIncreaseYear(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, n);
        return cal.getTime();
    }

    /**
     * 获取指定月份第一天最小的日期时间
     *
     * @param date 日期对象
     * @return 指定月份第一天最小的日期时间
     */
    public static Date getFirstDateLeastTimeOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }

    /**
     * 获取指定月份最后一天最大的日期时间
     *
     * @param date 日期对象
     * @return 指定月份最后一天最大的日期时间
     */
    public static Date getLastDateMaxTimeOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, cal.getActualMaximum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal.getActualMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getActualMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getActualMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }

    /**
     * 获取两个日期的时间间隔
     *
     * @param date1    开始日期
     * @param date2    结束日期
     * @param timeUnit 日期间隔换算单位
     * @return 根据提供的单位返回间隔值
     */
    public static Long getDateTimeDiff(Date date1, Date date2, TimeUnit timeUnit) {
        long diffInMillies = date2.getTime() - date1.getTime();
        return timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS);
    }

    /**
     * 获取两个日期的月份差
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 两个日期的月份差
     */
    public static Integer getDateMonthDiff(Date startDate, Date endDate) {
        Calendar startCalendar = new GregorianCalendar();
        startCalendar.setTime(startDate);
        Calendar endCalendar = new GregorianCalendar();
        endCalendar.setTime(endDate);

        int diffYear = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);
        return diffYear * 12 + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
    }

    /**
     * 根据日期跨度获取两个日期之间的所有间隔日期
     *
     * @param beginDate    开始日期（yyyy-MM-dd）
     * @param endDate      结束日期（yyyy-MM-dd）
     * @param calendarType 日期跨度类型 如：Calendar.DAY_OF_MONTH
     * @param step         步长，至少>=1
     * @return 两个日期之间的所有间隔日期
     */
    public static List<Date> getIntervalDateDiff(Date beginDate, Date endDate, int calendarType, int step) {
        List<Date> dates = new ArrayList<Date>();

        if (step < 1) {
            return dates;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginDate);

        while (calendar.getTime().compareTo(endDate) <= 0) {
            dates.add(calendar.getTime());
            calendar.add(calendarType, step);
        }
        return dates;
    }
}
